#include "tim3.h"

/************************************************************************
*函数名：TIM3_CH_Init
*函数功能：TIM3通道初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：TIM3_CH1——PC6——复用功能AF2
*************************************************************************/
void TIM3_CH_Init(void)
{
	/*使能GPIOC时钟*/
	RCC->AHB1ENR |= (1<<2);//使能GPIOC时钟

	/*配置GPIO控制器*/
	//模式寄存器——复用功能模式 10
	GPIOC->MODER &= ~	(3<<6*2);
	GPIOC->MODER |= 		(2<<6*2);//PC6
	GPIOC->MODER &= ~	(3<<7*2);
	GPIOC->MODER |= 		(2<<7*2);//PC7
	GPIOC->MODER &= ~	(3<<8*2);
	GPIOC->MODER |= 		(2<<8*2);//PC8
	GPIOC->MODER &= ~	(3<<9*2);
	GPIOC->MODER |= 		(2<<9*2);//PC9

	//输出类型寄存器——推挽 0
	GPIOC->OTYPER &= ~(1<<6);
	GPIOC->OTYPER &= ~(1<<7);
	GPIOC->OTYPER &= ~(1<<8);
	GPIOC->OTYPER &= ~(1<<9);

	//输出速度寄存器——低速 00
	GPIOC->OSPEEDR &= ~(3<<6*2);
	GPIOC->OSPEEDR &= ~(3<<7*2);
	GPIOC->OSPEEDR &= ~(3<<8*2);
	GPIOC->OSPEEDR &= ~(3<<9*2);

	//上拉/下拉寄存器——无上下拉 00
	GPIOC->PUPDR &= ~(3<<6*2);
	GPIOC->PUPDR &= ~(3<<7*2);
	GPIOC->PUPDR &= ~(3<<8*2);
	GPIOC->PUPDR &= ~(3<<9*2);

	//复用功能低位寄存器——AF2
	GPIOC->AFR[0] &= ~	(0xf<<6*4);
	GPIOC->AFR[0] |= 	(2<<6*4);//PC6
	GPIOC->AFR[0] &= ~	(0xf<<7*4);
	GPIOC->AFR[0] |= 	(2<<7*4);//PC7
	GPIOC->AFR[1] &= ~	(0xf<<0*4);
	GPIOC->AFR[1] |= 	(2<<0*4);//PC8
	GPIOC->AFR[1] &= ~	(0xf<<1*4);
	GPIOC->AFR[1] |= 	(2<<1*4);//PC9
}


/************************************************************************
*函数名：TIM3_Init
*函数功能：TIM3初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：1ms进一次中断
*************************************************************************/
void TIM3_Init(void)
{
	/*TIM3通道初始化配置*/
	TIM3_CH_Init();

	/*使能TIM3时钟*/
	RCC->APB1ENR |= (1<<1);

	/*配置TIM3时基单元*/
	TIM3->CNT = 0;//计数器清零
	TIM3->PSC = 84-1;//分频84
	TIM3->ARR = 256-1;//重装载值256（0.256ms更新一次）

	/*配置TIM3寄存器*/
	TIM3->CR1 |= (1<<7);//ARR寄存器进行缓冲
	TIM3->CR1 &= ~(1<<3);//计数器更新后不会停止，而是重新开始计数
	TIM3->CR1 &= ~(1<<2);
	TIM3->CR1 &= ~(1<<1);//使能更新事件

	/*软件更新（可选）*/
	TIM3->EGR |= (1<<0);//UG位置1，手动更新
	TIM3->SR &= ~(1<<0);//清零中断标志位

	/*CC1输出比较配置*/
	TIM3->CCMR1 &= ~(0xff<<0*8);//清零0-7位
	TIM3->CCMR1 |= (7<<4);//PWM模式2：递增计数时，先输出无效电平，后输出有效电平 111
	TIM3->CCER &= ~(0xf<<0*4);//清零0-3位（对应CC1通道）
	TIM3->CCER |= (1<<0);//使能输出比较 1
	TIM3->CCER |= (1<<1);//输出极性：低电平有效 1
	TIM3->CCR1 = 10;//CC1输出比较值

	/*CC1输入捕获配置*/

	/*CC2输出比较配置*/
	TIM3->CCMR1 &= ~(0xff<<1*8);//清零8-15位
	TIM3->CCMR1 |= (7<<12);//PWM模式2：递增计数时，先输出无效电平，后输出有效电平 111
	TIM3->CCER &= ~(0xf<<1*4);//清零4-7位（对应CC2通道）
	TIM3->CCER |= (1<<4);//使能输出比较 1
	TIM3->CCER |= (1<<5);//输出极性：低电平有效 1
	TIM3->CCR2 = 10;//CC2输出比较值

	/*CC3输出比较配置*/
	TIM3->CCMR2 &= ~(0xff<<0*8);//清零0-7位
	TIM3->CCMR2 |= (7<<4);//PWM模式2：递增计数时，先输出无效电平，后输出有效电平 111
	TIM3->CCER &= ~(0xf<<2*4);//清零8-11位（对应CC3通道）
	TIM3->CCER |= (1<<8);//使能输出比较 1
	TIM3->CCER |= (1<<9);//输出极性：低电平有效 1
	TIM3->CCR3 = 10;//CC3输出比较值

	/*打开计数器*/
	TIM3->CR1 |= (1<<0);

	/*开启TIM3中断*/
//	//在DIER开启更新中断
//	TIM3->DIER |= (1<<0);
//	//设置中断优先级
//	NVIC_SetPriority(TIM3_IRQn,NVIC_EncodePriority(7-2,2,3));//给TIM3设置优先级为(2,3)
//	//使能中断源
//	NVIC_EnableIRQ(TIM3_IRQn);
}

/************************************************************************
*函数名：TIM3_SetCCR1
*函数功能：设置TIM3的CCR1寄存器的值
*函数参数：u16 value，要设置的CCR1值
*函数返回值：无
*函数说明：
*				输入模式下，CCR1值是上一个捕获1事件发生时的CNT值；
*				输出模式下，CCR1值是与CNT进行输出比较的值。
*				CCR1值最好不要超过ARR的值（当前ARR：255）
*************************************************************************/
void TIM3_SetCCR1(u16 value)
{
	TIM3->CCR1 = value;
}

/************************************************************************
*函数名：TIM3_SetCCR2
*函数功能：设置TIM3的CCR2寄存器的值
*函数参数：u16 value，要设置的CCR2值
*函数返回值：无
*函数说明：
*				输入模式下，CCR2值是上一个捕获1事件发生时的CNT值；
*				输出模式下，CCR2值是与CNT进行输出比较的值。
*				CCR2值最好不要超过ARR的值（当前ARR：255）
*************************************************************************/
void TIM3_SetCCR2(u16 value)
{
	TIM3->CCR2 = value;
}

/************************************************************************
*函数名：TIM3_SetCCR3
*函数功能：设置TIM3的CCR3寄存器的值
*函数参数：u16 value，要设置的CCR3值
*函数返回值：无
*函数说明：
*				输入模式下，CCR3值是上一个捕获1事件发生时的CNT值；
*				输出模式下，CCR3值是与CNT进行输出比较的值。
*				CCR3值最好不要超过ARR的值（当前ARR：255）
*************************************************************************/
void TIM3_SetCCR3(u16 value)
{
	TIM3->CCR3 = value;
}


/************************************************************************
*函数名：TIM3_RGB_Color
*函数功能：设置RGB颜色值
*函数参数：u8 R,u8 G,u8 B	红，绿，蓝
*函数返回值：无
*函数说明：R/G/B取值范围：[0,255]，分别对应通道CC1，CC2，CC3
*************************************************************************/
void TIM3_RGB_Color(u8 R,u8 G,u8 B)
{
	TIM3_SetCCR1(R);
	TIM3_SetCCR2(G);
	TIM3_SetCCR3(B);
	//y = f(x,a,b,c,d)
	//y = (d-c)/(b-a)(x-a) + c
}

/************************************************************************
*函数名：TIM3_IRQHandler
*函数功能：TIM3中断服务函数
*函数参数：无
*函数返回值：无
*函数说明：
*************************************************************************/
void TIM3_IRQHandler(void)
{
	static u32 t3_time = 0;
	if (TIM3->SR & (1<<0))//如果是更新中断
	{
		TIM3->SR &= ~(1<<0);//清零中断标志位
		t3_time++;
		if (t3_time%1000 == 0)//每经过1s
		{
			printf("t3_time = %d\n",t3_time);
		}
	}
}
